<template>
  <div class="koi-flex">
    <cmeCard>
      <!-- 搜索区域 -->
      <div v-if="showSearch" class="search-area mb-4">
        <el-form ref="searchFormRef" :model="searchForm" :inline="true">
          <slot name="searchForm" :search-form="searchForm"></slot>
          <el-form-item>
            <el-button type="primary" :loading="loading" @click="handleSearch">
              <el-icon>
                <Search />
              </el-icon>搜索
            </el-button>
            <el-button type="danger" @click="handleReset">
              <el-icon>
                <Refresh />
              </el-icon>重置
            </el-button>
          </el-form-item>
        </el-form>
      </div>

      <!-- 表格工具栏 -->
      <div v-if="$slots.toolbar" class="mb-4">
        <el-row :gutter="10">
          <slot name="toolbar"></slot>
          <cmeToolbar v-model:showSearch="props.showSearch" @refreshTable="refreshTable"></cmeToolbar>
        </el-row>
      </div>

      <!-- 表格主体 -->
      <el-table ref="tableRef" v-bind="tableAttrs" v-loading="loading" :data="tableData" :border="border"
        :stripe="stripe" :row-key="rowKey" @selection-change="handleSelectionChange" @sort-change="handleSortChange">
        <!-- 选择列 -->
        <el-table-column v-if="showSelection" type="selection" width="55" align="center" fixed="left" />
        <!-- 序号列 -->
        <el-table-column v-if="showIndex" type="index" label="序号" width="60" align="center" />
        <!-- 表格列 -->
        <template v-for="(column, index) in columns" :key="index">
          <el-table-column v-bind="getColumnAttrs(column)">
            <template #default="scope">
              <slot :name="`column-${column.prop}`" :row="scope.row" :column="column" :index="scope.$index">
                {{ formatColumnValue(scope.row, column) }}
              </slot>
            </template>
          </el-table-column>
        </template>
        <!-- 操作列 -->
        <el-table-column v-if="$slots.operation" label="操作" :width="operationWidth" :fixed="operationFixed"
          align="center">
          <template #default="scope">
            <slot name="operation" :row="scope.row" :index="scope.$index"></slot>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div v-if="showPagination" class="pagination-area mt-4">
        <el-pagination v-model:current-page="pagination.currentPage" v-model:page-size="pagination.pageSize"
          :page-sizes="pageSizes" :total="total" :layout="paginationLayout" @size-change="handleSizeChange"
          @current-change="handleCurrentChange" />
      </div>
    </cmeCard>
  </div>
</template>

<script setup>
import { ref, reactive, computed, watch } from 'vue'
import { Search, Refresh } from '@element-plus/icons-vue'
/** 是否显示搜索表单 */
const props = defineProps({
  // 表格列配置
  columns: {
    type: Array,
    required: true
  },
  // 表格数据
  data: {
    type: Array,
    default: () => []
  },
  // 是否显示搜索区域
  showSearch: {
    type: Boolean,
    default: true
  },
  // 是否显示分页
  showPagination: {
    type: Boolean,
    default: true
  },
  // 是否显示选择列
  showSelection: {
    type: Boolean,
    default: false
  },
  // 是否显示序号列
  showIndex: {
    type: Boolean,
    default: true
  },
  // 是否带边框
  border: {
    type: Boolean,
    default: true
  },
  // 是否斑马纹
  stripe: {
    type: Boolean,
    default: true
  },
  // 行数据的 Key
  rowKey: {
    type: String,
    default: 'id'
  },
  // 操作列宽度
  operationWidth: {
    type: [String, Number],
    default: 150
  },
  // 操作列是否固定
  operationFixed: {
    type: String,
    default: 'right'
  },
  // 分页大小选项
  pageSizes: {
    type: Array,
    default: () => [10, 20, 50, 100]
  },
  // 分页布局
  paginationLayout: {
    type: String,
    default: 'total, sizes, prev, pager, next, jumper'
  },
  // 数据总数
  total: {
    type: Number,
    default: 0
  },
  // 额外的表格属性
  tableAttrs: {
    type: Object,
    default: () => ({})
  }
})

const emit = defineEmits([
  'update:data',
  'selection-change',
  'sort-change',
  'search',
  'reset',
  'page-change'
])

// 组件实例
const tableRef = ref(null)
const searchFormRef = ref(null)

// 状态
const loading = ref(false)
const searchForm = reactive({})
const tableData = ref(props.data)
const pagination = reactive({
  currentPage: 1,
  pageSize: 10
})

// 选中的行数据
const selectedRows = ref([])

// 格式化列值
const formatColumnValue = (row, column) => {
  const value = row[column.prop]
  if (column.formatter) {
    return column.formatter(row, column, value)
  }
  if (column.dict) {
    return column.dict[value] || value
  }
  
  return value
}
const refreshTable = () => {
  handleReset()
  handleSearch()
}

// 获取列属性
const getColumnAttrs = (column) => {
  return {
    prop: column.prop,
    label: column.label,
    width: column.width,
    minWidth: column.minWidth,
    align: column.align || 'left',
    sortable: column.sortable,
    fixed: column.fixed,
    showOverflowTooltip: column.showOverflowTooltip ?? true,
    ...column.attrs
  }
}

// 搜索
const handleSearch = async () => {
  loading.value = true
  try {
    emit('search', { ...searchForm, ...pagination })
  } finally {
    loading.value = false
  }
}

// 重置
const handleReset = () => {
  searchFormRef.value?.resetFields()
  pagination.currentPage = 1
  emit('reset')
}

// 选择变化
const handleSelectionChange = (selection) => {
  selectedRows.value = selection
  emit('selection-change', selection)
}

// 排序变化
const handleSortChange = (sort) => {
  emit('sort-change', sort)
}

// 页码变化
const handleCurrentChange = (current) => {
  pagination.currentPage = current
  emit('page-change', pagination)
}

// 页大小变化
const handleSizeChange = (size) => {
  pagination.pageSize = size
  pagination.currentPage = 1
  emit('page-change', pagination)
}

// 监听数据变化
watch(
  () => props.data,
  (val) => {
    tableData.value = val
  },
  { deep: true }
)

// 暴露方法
defineExpose({
  tableRef,
  searchFormRef,
  selectedRows,
  reload: handleSearch,
  reset: handleReset
})
</script>

<style lang="scss" scoped></style>
